package lib.player;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.util.ArrayList;

import lib.Commands;
import lib.Config;
import lib.Parser;
import lib.Universe;
import lib.Utils;
import lib.map.Map;

public class PlayerList {
	public Parser parser ;
	Utils util = new Utils();
	// private Sound collision = new Sound("data/sounds/explosion.wav");
	public ArrayList<Player> list;
	float xGrid;
	float yGrid;

	int xPart;
	int yPart;
	Image Textures[];
	Map map;

	/**
	 * 
	 * @param xRes
	 * @param yRes
	 * @param map
	 */
	public PlayerList(Map map) {
		list = new ArrayList<Player>();
		this.map = map;
		parser=map.parser;		
		this.xPart = map.xPart * 10;
		this.yPart = map.yPart * 10;
		this.xGrid = (float) Config.xRes / xPart;
		this.yGrid = (float) Config.yRes / xPart;// yea all rigth
		System.out.println(Config.xRes + "|" + Config.yRes + "|" + xGrid + "|" + yGrid + "|"
				+ xPart + "|" + yPart);		

		Textures = util.imageLodaer(new String[] {
				"data/textures/player/2.png", "data/textures/player/3.png",
				"data/textures/player/4.png" });

	}

	/**
	 * Add a player to PlayerList
	 * 
	 * @param player
	 */
	public void add(Player pl) {
		list.add(pl);
	}

	/**
	 * Remove a Player from PlayerList
	 * 
	 * @param player
	 */
	public void remove(Player pl) {
		list.remove(pl);
	}

	/**
	 * 
	 * @return the length of the Playerlist
	 */
	public int length() {
		return list.size();
	}

	/**
	 * Draws every Player
	 * 
	 * @param g
	 * @param Coll
	 * @param Row
	 * @return Graphics
	 */
	public void draw(Graphics2D g, Player pl, int phase) {
		int Row = (int) pl.yPos - yPart / 2;
		int Coll = (int) pl.xPos - xPart / 2;

		// Check That Coordinates are valid
		if (Coll < 0)
			Coll = 0;
		if (Coll + xPart >= Config.CollumnCount * 10)
			Coll = (Config.CollumnCount * 10) - xPart;
		if (Row < 0)
			Row = 0;
		if (Row + yPart > Config.RowCount * 10)
			Row = (Config.RowCount * 10) - yPart;
		// draws the player if in displayed area

		Graphics2D g2d = (Graphics2D) g;

		for (Player pls : list) {
			if (pls.xPos >= Coll && pls.xPos < Coll + xPart && pls.yPos >= Row
					&& pls.yPos < Row + yPart) {
				// drawing opf the players
				g2d.setColor(pls.color);

				g2d.drawString(pls.DisplayName + " Nr." + pls.nr + ".",
						(int) (xGrid * (pls.xPos - Coll)),
						(int) (yGrid * (pls.yPos - Row)) - 10);
				// g2d.drawString(pls.life + "%", (int) (xGrid * (pls.xPos -
				// Coll)) + 5,(int) (yGrid * (pls.yPos - Row)));
				int x = (int) ((xGrid * (pls.xPos - Coll)));
				int y = (int) ((yGrid * (pls.yPos - Row)));
				double rotate = pls.direction * 45;
				g2d.rotate(rotate, x + map.xGrid / 2, y + map.xGrid / 2);
				g2d.fillOval(x + map.xGrid / 3, y + map.xGrid / 5,
						map.xGrid / 4, map.xGrid / 4);
				g2d.drawImage(getTexture(phase), x, y, map.xGrid, map.xGrid,
						null);
				g2d.rotate(-rotate, x + map.xGrid / 2, y + map.xGrid / 2);
			}
		}
	}

	/**
	 * 
	 * @param val
	 *            Phase for animation
	 * @return Image
	 */

	public Image getTexture(int val) {
		return Textures[val % Textures.length];
	}

	/**
	 * Draws the Players on the minimap
	 * 
	 * @param g
	 * @return Graphics
	 */
	public Graphics drawMiniMap(Graphics g, float resizeFactor) {
		for (Player pl : list) {
			g.setColor(pl.color);
			g.fillRect((int) (pl.xPos * Config.xRes / 1000 * resizeFactor),
					(int) (pl.yPos * Config.yRes / 1000 * resizeFactor), 2, 2);
		}
		return g;
	}

	/**
	 * Moves the Player if move is allowed
	 * 
	 * @param Player
	 * @param x
	 * @param y
	 * @param thread
	 */
	public boolean move(Player pl, int x, int y, Universe uni) {
		if (pl.xPos == x && pl.yPos == y)
			return true;
		if (x < 0 || x >= Config.CollumnCount * 10)
			return false;
		if (y < 0 || y >= Config.RowCount * 10)
			return false;
		if (map.checkPickable(x, y)) {
			if (pl.ITEM.NR == 0) {
				int ele = map.getField(x / 10, y / 10).NR;
				pl.ITEM = parser.items.get(ele);
				map.setField(0, x / 10, y / 10);
				uni.broadcast(Commands.ITEM, pl.nr + " " + ele);
				uni.broadcast(Commands.SETMAP, "false 0 " + x / 10 + " " + y
						/ 10);
				if (collision(pl, x, y, uni)) {
					// collision.play();
					return false;
				}

				pl.xPos = x;
				pl.yPos = y;
				pl.updateDirection();
				return true;
			}
		}
		if (map.checkCollision(x, y, pl.ITEM.damage)) {
			// collision.play();
			return false;
		}
		if (collision(pl, x, y, uni)) {
			// collision.play();
			return false;
		}
		pl.xPos = x;
		pl.yPos = y;
		pl.updateDirection();
		return true;
	}

	/**
	 * Returns if there is a collision betwen two Players
	 * 
	 * @param Player
	 * @param x
	 * @param y
	 * @param uni
	 * @return boolean
	 */
	public boolean collision(Player pl, int x, int y, Universe uni) {
		for (Player test : list) {
			if (!test.equals(pl)) {
				if (Math.pow(test.xPos - (x), 2) < 50
						&& Math.pow(test.yPos - (y), 2) < 100) {
					pl.ITEM.respwan(map, pl, uni, this, 5);
					test.ITEM.respwan(map, test, uni, this, 5);
					return true;
				}
			}
		}
		return false;
	}

	public void simpleMove(Player pl, int x, int y) {
		pl.xPos = x;
		pl.yPos = y;
	}

	/**
	 * 
	 * @param nr
	 *            Player Identifier nr
	 * @return Player
	 */
	public Player getPlayer(int nr) throws NullPointerException {
		for (Player pl : list) {
			if (pl.nr == nr)
				return pl;
		}
		throw new NullPointerException();
	}

	/**
	 * 
	 * @param name
	 *            Player Name
	 * @return Player
	 */
	public Player getPlayer(String name) throws NullPointerException {
		for (Player pl : list) {
			if (pl.name.equals(name))
				return pl;
		}
		throw new NullPointerException();
	}

	public String[] score() {
		String[] out = new String[list.size()];
		int i = 0;
		for (Player p : list) {
			out[i++] = p.DisplayName + ": " + p.points + "   Item: "
					+ p.ITEM.Name;
		}
		return out;
	}
}
